<template>
  <el-form-item
      v-bind="item"
      v-if="item.hiddenSeat!==true"
      :rules="formItemRules(item)"
  >
    <component
        :is="'DynamicForm'+item.type"
        :item="item"
        :formData="formData"
        :formVm="formVm"
        ref="component"
    ></component>
    <template
        v-if="hasSlotName('error')"
        #error="{error}">
      <RenderVnodes
          :vnodes="slot('error',{
          error
        })"
      ></RenderVnodes>
    </template>
    <template
        v-if="hasSlotName('label')"
        #label="{label}">
      <RenderVnodes
          :vnodes="slot('label',{
          label
        })"
      ></RenderVnodes>
    </template>
  </el-form-item>
</template>

<script lang="ts">
import {BaseCommonMixin} from "./mixins/BaseCommonMixin";
import {getComponents} from "./componentsConfig";
import {FormConfigItem} from "./types";
import {deepClone} from "../../utils";
import typeOfUtils from "../../utils/type-of-utils";

export default {
  name: 'FromItem',
  mixins:[BaseCommonMixin],
  components:getComponents(),
  watch: {
    item: {
      deep: true,
      immediate: true,
      handler(val:FormConfigItem) { // 组件配置检测
        if(!val.type) { // 如果没有配置类型
          console.error('当前配置没有type',val) // 提示item
          return
        }
        if(val.type !== 'slot') { // 如果不是插槽
          if(!val.prop) { // 且没有字段配置
            console.error('当前配置没有prop',val) // 提示item
          }
        }
      }
    }
  },
  methods:{
    async resetField() {
      while (!this.$refs.component) {
        await this.sleep()
      }
      let i = this.$refs.component
      if (i.resetField) {
        i.resetField()
      } else {
        console.warn(i.$options.name, '子组件不存在resetField')
      }
    },
    formItemRules(item: FormConfigItem) {
      let result = []
      if (item.rules) {
        result = item.rules.map(i => {
          let item1 = deepClone(i)
          if (i.validator) {
            item1.validator = (rule, value, callback) => {
              i.validator(rule, value, callback, this.formData, item)
            }
          }
          if (i.asyncValidator) {
            delete item1.asyncValidator
            item1.validator = (rule, value, callback) => {
              const res = i.asyncValidator(rule, value, this.formData, item);
              if (typeOfUtils.isPromise(res)) {
                (res as Promise<string>).then(r => {
                  callback()
                }).catch(e => {
                  callback(new Error(e))
                })
              } else if (typeOfUtils.isError(res)) {
                callback(res as Error)
              } else {
                callback()
              }
            }
          }
          return item1
        })
      }
      return result
    },
    slotName(name){
      if(name === 'label') {
        return this.item.labelSlotName
      }
      if(name==='error'){
        return this.item.errorSlotName
      }
      return ''
    },
  }
}
</script>

<style lang="scss" scoped>

</style>
